Skip to main content

15 浮点数和定点数

浮点数的不精确性

0.3 + 0.6;
0.8999999999999999;

定点数的表示

BCD 编码(Binary-Coded Decimal):用 4 个比特来表示 0 ~ 9 的整数,32 个比特表示 8 个这样的整数。把最右边的 2 个 0 ~ 9 的整数,当成小数部分;把左边 6 个 0 ~ 9 的整数,当成整数部分。可以用 32 个比特,来表示从 0 到 999999.99 这样 1 亿个实数。

超市、银行需要用小数记录金额的情况

缺点

  1. 有点“浪费”位数
  2. 没办法同时表示很大的数字和很小的数字

浮点数的表示

10 的 82 次方 => 1.0×1082

float 或者 float32 类型:用 32 比特表示单精度的浮点数。

double 或者 float64 类型:用 64 比特表示双精度的浮点数。

单精度类型

符号位:用来表示是正数还是负数。

指数位:用 1 ~ 254 映射到 -126 ~ 127 这 254 个有正有负的数上。

有效数位:表示有效数位

(−1)s×1.f×2e

0.5=(−1)0×1.0×2−1=0.5

浮点数的二进制转化

符号位 s+ 指数位 e+ 有效位数 f

整数部分变成二进制

小数部分变成二进制

2 的 -N 次方

(2) 0.1001 = 1×2−1+0×2−2+0×2−3+1×2−4 = 0.5625

小数部分转换成二进制,乘以 2 看是否超过 1。如果超过 1 就记下 1,并把结果减去 1,进一步循环操作。

(10) 0.1 = 0.000110011

9.1 = 1001.000110011… = 1.001000110011…×23

符号位 s = 0

有效位 f =001000110011… = 00100011001100110011 001 (23 位)

指数 e = 3

再转换为十进制 = 9.09999942779541015625

浮点数可视化展示

浮点数的加法和精度损失

浮点数加法:先对齐、再计算

两个浮点数的指数位可能不一样,把两个的指数位变成一样的,然后只去计算有效位的加法

0.5+0.125

指数位较小的数,需要在有效位进行右移,最右侧的有效位被丢弃掉。导致对应的指数位较小的数,在加法发生之前,就丢失精度。两个相加数的指数位差的越大,位移的位数越大,可能丢失的精度也就越大。

Kahan Summation 算法

浮点数存在精度损失,银行存款、电商交易需要精确计算

在每次的计算过程中,都用一次减法,把当前加法计算中损失的精度记录下来,然后在后面的循环中,把这个精度损失放在要加的小数上,再做一次运算。对应的数学证明